import 'dart:convert';

import 'package:chathouse/constant/app_constant.dart';
import 'package:chathouse/net/Apis.dart';
import 'package:chathouse/util/log.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:synchronized/synchronized.dart';
// import 'package:flutter_app_badger/flutter_app_badger.dart';

// 数据储存
class SpUtil {
  static SpUtil? _singleton;
  static SharedPreferences? _prefs;
  static Lock _lock = Lock();

  static Future<SpUtil> getInstance() async {
    if (_singleton == null) {
      await _lock.synchronized(() async {
        if (_singleton == null) {
          // 保持本地实例直到完全初始化。
          var singleton = SpUtil._();
          await singleton._init();
          _singleton = singleton;
        }
      });
    }
    return _singleton!;
  }

  SpUtil._();

  Future _init() async {
    _prefs = await SharedPreferences.getInstance();
  }

  /// put object.
  static Future<bool>? putObject(String key, Object value) {
    if (_prefs == null) return null;
    return _prefs?.setString(key, value == null ? "" : json.encode(value));
  }

  /// get object.
  static Map? getObject(String key) {
    if (_prefs == null) return null;
    String? _data = _prefs?.getString(key);
    return (_data == null || _data.isEmpty) ? null : json.decode(_data);
  }

  /// get object.
  static Object? getObject2(String key) {
    if (_prefs == null) return null;
    String? _data = _prefs?.getString(key);
    return (_data == null || _data.isEmpty) ? null : json.decode(_data);
  }

  /// put object list.
  static Future<bool>? putObjectList(String key, List<Object> list) {
    if (_prefs == null) return null;
    List<String>? _dataList = list.map((value) {
      return json.encode(value);
    }).toList();
    return _prefs!.setStringList(key, _dataList);
  }

  /// get object list.
  static List<Map>? getObjectList(String key) {
    if (_prefs == null) return null;
    List<String>? dataLis = _prefs?.getStringList(key);
    return dataLis?.map((value) {
      Map _dataMap = json.decode(value);
      return _dataMap;
    })?.toList();
  }

  /// get string.
  static String getString(String key, {String defValue = ''}) {
    if (_prefs == null) return defValue;
    return _prefs!.getString(key) ?? defValue;
  }

  /// put string.
  static Future<bool>? putString(String key, String value) {
    if (_prefs == null) return null;
    return _prefs!.setString(key, value);
  }

  /// get bool.
  static bool getBool(String key, {bool defValue = false}) {
    print(_prefs);
    if (_prefs == null) return defValue;
    return _prefs!.getBool(key) ?? defValue;
  }

  /// put bool.
  static Future<bool>? putBool(String key, bool value) {
    if (_prefs == null) return null;
    return _prefs!.setBool(key, value);
  }

  /// get int.
  static int getInt(String key, {int defValue = 0}) {
    if (_prefs == null) return defValue;
    return _prefs!.getInt(key) ?? defValue;
  }

  /// put int.
  static Future<bool>? putInt(String key, int value) {
    if (_prefs == null) return null;
    return _prefs!.setInt(key, value);
  }

  /// get double.
  static double getDouble(String key, double defValue) {
    if (_prefs == null) return defValue;
    return _prefs!.getDouble(key) ?? defValue;
  }

  /// put double.
  static Future<bool>? putDouble(String key, double value) {
    if (_prefs == null) return null;
    return _prefs!.setDouble(key, value);
  }

  /// get string list.
  static List<String> getStringList(String key,
      {List<String> defValue = const []}) {
    if (_prefs == null) return defValue;
    return _prefs!.getStringList(key) ?? defValue;
  }

  /// put string list.
  static Future<bool>? putStringList(String key, List<String> value) {
    if (_prefs == null) return null;
    return _prefs!.setStringList(key, value);
  }

  /// get dynamic.
  static dynamic getDynamic(String key, {required Object defValue}) {
    if (_prefs == null) return defValue;
    return _prefs!.get(key) ?? defValue;
  }

  /// have key.
  static bool? haveKey(String key) {
    if (_prefs == null) return null;
    return _prefs!.getKeys().contains(key);
  }

  /// get keys.
  static Set<String>? getKeys() {
    if (_prefs == null) return null;
    return _prefs!.getKeys();
  }

  /// remove.
  static Future<bool>? remove(String key) {
    if (_prefs == null) return null;
    return _prefs!.remove(key);
  }

  /// clear.
  static Future<bool>? clear() {
    if (_prefs == null) return null;
    //登出
    Apis.loginOut({}).then((value) => null).catchError((error) {
      LogUtil.d("loginOut error $error");
    });
    showBadge(0);
    // FlutterAppBadger.removeBadge();
    // get Login info. before clear
    bool cRememberMe = getBool(
        AppConstant.cRememberMe
    );
    String cLoginArea = getString(
        AppConstant.cLoginArea
    );
    String cLoginPhone = getString(
      AppConstant.cLoginPhone
    );
    String cLoginEmail = getString(
      AppConstant.cLoginEmail
    );
    String cLoginPwd = getString(
      AppConstant.cLoginPwd
    );

    bool bRememberMe = getBool(
        AppConstant.bRememberMe
    );
    String bLoginArea = getString(
        AppConstant.bLoginArea
    );
    String bLoginPhone = getString(
      AppConstant.bLoginPhone
    );
    String bLoginEmail = getString(
      AppConstant.bLoginEmail
    );
    String bLoginPwd = getString(
      AppConstant.bLoginPwd
    );

    Future<bool>? clear = _prefs!.clear();
    // put Login info. back
    putBool(AppConstant.cRememberMe, cRememberMe);
    putString(AppConstant.cLoginArea, cLoginArea);
    putString(AppConstant.cLoginPhone, cLoginPhone);
    putString(AppConstant.cLoginEmail, cLoginEmail);
    putString(AppConstant.cLoginPwd, cLoginPwd);

    putBool(AppConstant.bRememberMe, bRememberMe);
    putString(AppConstant.bLoginArea, bLoginArea);
    putString(AppConstant.bLoginPhone, bLoginPhone);
    putString(AppConstant.bLoginEmail, bLoginEmail);
    putString(AppConstant.bLoginPwd, bLoginPwd);

    return clear;
  }

  static Future<Null> showBadge(int num) async {
    const badgeChannel = MethodChannel("chathouse.flutter");
    try {
      final result = await badgeChannel.invokeMethod('getBadge', {
        "badgeNum": num,
      });
    } on PlatformException catch (e) {
      if (kDebugMode) {
        LogUtil.d("_showBadge error: ${e.message}");
      }
    }
  }

  /// clear.
  static Future<bool>? onClearClear() {
    if (_prefs == null) return null;
    // get Login info. before clear
    bool cRememberMe = getBool(
        AppConstant.cRememberMe
    );
    String cLoginArea = getString(
        AppConstant.cLoginArea
    );
    String cLoginPhone = getString(
        AppConstant.cLoginPhone
    );
    String cLoginEmail = getString(
        AppConstant.cLoginEmail
    );
    String cLoginPwd = getString(
        AppConstant.cLoginPwd
    );

    bool bRememberMe = getBool(
        AppConstant.bRememberMe
    );
    String bLoginArea = getString(
        AppConstant.bLoginArea
    );
    String bLoginPhone = getString(
        AppConstant.bLoginPhone
    );
    String bLoginEmail = getString(
        AppConstant.bLoginEmail
    );
    String bLoginPwd = getString(
        AppConstant.bLoginPwd
    );

    Future<bool>? clear = _prefs!.clear();
    // put Login info. back
    putBool(AppConstant.cRememberMe, cRememberMe);
    putString(AppConstant.cLoginArea, cLoginArea);
    putString(AppConstant.cLoginPhone, cLoginPhone);
    putString(AppConstant.cLoginEmail, cLoginEmail);
    putString(AppConstant.cLoginPwd, cLoginPwd);

    putBool(AppConstant.bRememberMe, bRememberMe);
    putString(AppConstant.bLoginArea, bLoginArea);
    putString(AppConstant.bLoginPhone, bLoginPhone);
    putString(AppConstant.bLoginEmail, bLoginEmail);
    putString(AppConstant.bLoginPwd, bLoginPwd);

    return clear;
  }

  ///Sp is initialized.
  static bool isInitialized() {
    return _prefs != null;
  }
}
